package com.gitee.cnlongs.cnlongmq.basic.entitiy.request;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.gitee.cnlongs.cnlongmq.basic.constant.CnLongMqConstant;
import com.gitee.cnlongs.cnlongmq.basic.entitiy.election.CaptainElectionEntity;

/**
 * 系统名称：CnLongMqConfiger.java
 * 模块名称：
 * 模块描述：中国龙[消息队列] - 配置实体总类
 * 功能列表：
 * 模块作者：ZOUYONG
 * 开发时间：2019年3月31日 下午12:14:10
 * 模块路径：com.gitee.cnlongs.cnlongmq.basic.entitiy.request.CnLongMqConfiger
 * 更新记录：
 */
public class CnLongMqConfiger implements Serializable {

	// 序列化ID
	private static final long serialVersionUID = 1L;
	
	// mq服务器的名称，全网唯一，不允许重复
	private String longMqName;
	
	// mq服务器ip
	private String longMqIp;

	// mq服务器端口
	private Integer longMqPort;
	
	// mq服务消息存储目录
	private String longMqPath;

	// mq消息超时时间，单位为秒，0-马上过期，小于0-则不过期
	private Integer longMqExpTimeOut = CnLongMqConstant.defaultLongMqTimeOut;
	
	// 发送MQ消息的超时时间(单位为秒)
	private Integer longMqSendTimeOut = CnLongMqConstant.defaultLongMqSendTimeOut;
	
	// MQ消息发送失败，重发的时间(单位为秒)
	private Integer againSendFailMessageTime = CnLongMqConstant.defaultAgainSendFailMqMessageTime;
	
	// mq关联的消费端队列
	private String customer;
	
	// 消息数据持久化分区等配置目录
	private String dbConfigPath;
	
	// 消息数据-时间分区配置
	private String dataTimeMatching;
	
	// 配置文件生成时间
	private Date createDate = new Date();
	
	// ============================== 以下是解析配置文件合成的属性 ==============================
	
	// 本应用mq配置的队列列表
	private List<CnLongMessageQueue> sequeueList = new ArrayList<CnLongMessageQueue>();
	
	// 本应用及关联应用配置的所有队列列表
	private List<CnLongMessageQueue> customerSequeueList = new ArrayList<CnLongMessageQueue>();
	
	// 关联应用配置的所有队列列表
	private List<CnLongMessageQueue> appRelationSequeueList = new ArrayList<CnLongMessageQueue>();
	
	// 本应用及关联应用的基础信息列表
	private List<String> applicationList = new ArrayList<String>();
	
	// 需要执行同步队列的客户端列表
	private List<String> customerList = new ArrayList<String>();

	// ============================== 以下是交换队列信息时需要用到的属性 ==============================
	
	// 已经同步成功/同步失败的队列客户端列表
	private Map<String, Long> alreadyOpertorCustomerMap = new HashMap<String, Long>();
	
	// 当前同步中队列的线程编号
	private String syncThreadCode;

	// ============================== 以下是队列选举需要用到的属性 ==============================
	
	// 已选举成功为【队长】的队列信息，格式是【ip:端口:选举时间】
	private String captainElectionSequeue;

	// 本机应用初选时间
	private Long captainElectionTime;
	
	// 后补队长信息列表
	private Map<String, CaptainElectionEntity> captainElectionMap = new HashMap<String, CaptainElectionEntity>();
	
	public CnLongMqConfiger() {}
	
	public CnLongMqConfiger(String longMqName, String longMqIp, int longMqPort, String longMqPath, Integer longMqTimeOut) {
		this.longMqName = longMqName;
		this.longMqIp = longMqIp;
		this.longMqPort = longMqPort;
		this.longMqPath = longMqPath;
		if(null == longMqTimeOut) {
			longMqTimeOut = CnLongMqConstant.defaultLongMqTimeOut;
		}
	}

	/**
	 * 功能描述：检查配置信息必填项是否完整
	 × 模块作者：ZOUYONG
	 × 开发时间：2019年8月1日 下午4:29:46
	 × 返回数据：void
	 */
	public void check() {
		if(StringUtils.isBlank(this.longMqName) || StringUtils.isBlank(this.longMqIp) || StringUtils.isBlank(this.longMqPath)) {
			throw new RuntimeException(CnLongMqConstant.longmqDefaultName + "配置信息为空！");
		}
	}

	/**
	 * 功能描述：获取所关联应用的队列列表
	 × 模块作者：ZOUYONG
	 × 开发时间：2019年8月1日 下午4:30:19
	 × 返回数据：List<CnLongMessageQueue>
	 */
	public List<CnLongMessageQueue> getAppRelationSequeueList() {
		this.appRelationSequeueList.clear();
		for(CnLongMessageQueue custQueue: customerSequeueList) {
			boolean status = true;
			for(CnLongMessageQueue currQueue: sequeueList) {
				if(custQueue.getId().equals(currQueue.getId())) {
					status = false;
					break;
				}
			}
			if(status) {
				this.appRelationSequeueList.add(custQueue);
			}
		}
		return appRelationSequeueList;
	}

	/**
	 * 功能描述：获取本应用和关联应用基础信息
	 × 模块作者：ZOUYONG
	 × 开发时间：2019年8月1日 下午4:30:36
	 × 返回数据：List<String>
	 */
	public List<String> getApplicationList() {
		this.applicationList.clear();
		String currAppStr = this.longMqIp+CnLongMqConstant.longmqSeparateF+this.longMqPort;
		for(CnLongMessageQueue queue: customerSequeueList) {
			String appStr = queue.getLongMqIp()+CnLongMqConstant.longmqSeparateF+queue.getLongMqPort();
			if(!this.applicationList.contains(appStr) && !appStr.equals(currAppStr)) {
				this.applicationList.add(appStr);
			}
		}
		for(String appStr : customerList) {
			if(!this.applicationList.contains(appStr) && !appStr.equals(currAppStr)) {
				this.applicationList.add(appStr);
			}
		}
		return applicationList;
	}

	/**
	 * 功能描述：选举自身为队长
	 × 模块作者：ZOUYONG
	 × 开发时间：2019年8月1日 下午4:30:57
	 × 返回数据：String
	 */
	public String electionOwnCaptain() {
		this.captainElectionTime = new Date().getTime();
		this.setCaptainElectionSequeue(
				this.longMqIp+CnLongMqConstant.longmqSeparateF+
				this.longMqPort+CnLongMqConstant.longmqSeparateF+
				this.captainElectionTime);
		return this.captainElectionSequeue;
	}

	/**
	 * 功能描述：获取指定角色的队列列表
	 × 模块作者：ZOUYONG
	 × 开发时间：2019年8月5日 上午9:22:03
	 × 返回数据：List<CnLongMessageQueue>
	 */
	public List<CnLongMessageQueue> getCustomerSequeueList(String role) {
		List<CnLongMessageQueue> queueList = new ArrayList<CnLongMessageQueue>();
		for (int i=0; i<customerSequeueList.size(); i++) {
			CnLongMessageQueue queue = customerSequeueList.get(i);
			if(StringUtils.isNotBlank(queue.getRole()) && queue.getRole().equals(role)) {
				queueList.add(queue);
			}
		}
		return queueList;
	}

	public void setApplicationList(List<String> applicationList) {
		this.applicationList = applicationList;
	}

	public void setAppRelationSequeueList(List<CnLongMessageQueue> appRelationSequeueList) {
		this.appRelationSequeueList = appRelationSequeueList;
	}

	public String getLongMqName() {
		return longMqName;
	}

	public void setLongMqName(String longMqName) {
		this.longMqName = longMqName;
	}

	public String getLongMqIp() {
		return longMqIp;
	}

	public void setLongMqIp(String longMqIp) {
		this.longMqIp = longMqIp;
	}

	public Integer getLongMqPort() {
		return longMqPort;
	}

	public void setLongMqPort(Integer longMqPort) {
		this.longMqPort = longMqPort;
	}

	public String getLongMqPath() {
		return longMqPath;
	}

	public void setLongMqPath(String longMqPath) {
		this.longMqPath = longMqPath;
	}

	public Integer getLongMqExpTimeOut() {
		return longMqExpTimeOut;
	}

	public void setLongMqExpTimeOut(Integer longMqExpTimeOut) {
		this.longMqExpTimeOut = longMqExpTimeOut;
	}

	public String getCustomer() {
		return customer;
	}

	public void setCustomer(String customer) {
		this.customer = customer;
	}

	public String getDbConfigPath() {
		return dbConfigPath;
	}

	public void setDbConfigPath(String dbConfigPath) {
		this.dbConfigPath = dbConfigPath;
	}

	public List<CnLongMessageQueue> getSequeueList() {
		return sequeueList;
	}

	public void setSequeueList(List<CnLongMessageQueue> sequeueList) {
		this.sequeueList = sequeueList;
	}

	public String getSyncThreadCode() {
		return syncThreadCode;
	}

	public void setSyncThreadCode(String syncThreadCode) {
		this.syncThreadCode = syncThreadCode;
	}

	public List<String> getCustomerList() {
		return customerList;
	}

	public void setCustomerList(List<String> customerList) {
		this.customerList = customerList;
	}

	public List<CnLongMessageQueue> getCustomerSequeueList() {
		return customerSequeueList;
	}

	public void setCustomerSequeueList(List<CnLongMessageQueue> customerSequeueList) {
		this.customerSequeueList = customerSequeueList;
	}

	public String getDataTimeMatching() {
		return dataTimeMatching;
	}

	public void setDataTimeMatching(String dataTimeMatching) {
		this.dataTimeMatching = dataTimeMatching;
	}

	public Integer getLongMqSendTimeOut() {
		return longMqSendTimeOut;
	}

	public void setLongMqSendTimeOut(Integer longMqSendTimeOut) {
		this.longMqSendTimeOut = longMqSendTimeOut;
	}

	public Integer getAgainSendFailMessageTime() {
		return againSendFailMessageTime;
	}

	public void setAgainSendFailMessageTime(Integer againSendFailMessageTime) {
		this.againSendFailMessageTime = againSendFailMessageTime;
	}

	public Map<String, Long> getAlreadyOpertorCustomerMap() {
		return alreadyOpertorCustomerMap;
	}

	public void setAlreadyOpertorCustomerMap(Map<String, Long> alreadyOpertorCustomerMap) {
		this.alreadyOpertorCustomerMap = alreadyOpertorCustomerMap;
	}

	public String getCaptainElectionSequeue() {
		return captainElectionSequeue;
	}

	public void setCaptainElectionSequeue(String captainElectionSequeue) {
		this.captainElectionSequeue = captainElectionSequeue;
	}

	public Date getCreateDate() {
		return createDate;
	}

	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}

	public Map<String, CaptainElectionEntity> getCaptainElectionMap() {
		return captainElectionMap;
	}

	public void setCaptainElectionMap(Map<String, CaptainElectionEntity> captainElectionMap) {
		this.captainElectionMap = captainElectionMap;
	}

	public Long getCaptainElectionTime() {
		return captainElectionTime;
	}

	public void setCaptainElectionTime(Long captainElectionTime) {
		this.captainElectionTime = captainElectionTime;
	}

}
